package ua.com.alus.resvac.crm.stripes.action.account;

import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.integration.spring.SpringBean;
import net.sourceforge.stripes.validation.EnumeratedTypeConverter;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import net.sourceforge.stripes.validation.ValidationErrors;
import net.sourceforge.stripes.validation.ValidationMethod;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import ua.com.alus.resvac.crm.domen.entities.Account;
import ua.com.alus.resvac.crm.domen.entities.Photo;
import ua.com.alus.resvac.crm.services.spring.AccountService;
import ua.com.alus.resvac.crm.stripes.base.BaseAction;
import ua.com.alus.resvac.crm.util.EncriptionUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.UUID;

/**
 * Register Account abstract action
 * Created by Usatov Alexey
 */
public abstract class RegisterAccount extends BaseAction {

    private static final Logger LOGGER = Logger.getLogger(RegisterAccount.class);

    @SpringBean("/account/accountService")
    protected AccountService accountService;

    @ValidateNestedProperties({
            @Validate(field = "userName", required = true, minlength = 3, mask = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"),
            @Validate(field = "password", required = true, minlength = 6),
            @Validate(field = "rePassword", required = true, minlength = 6),
            @Validate(field = "accountType", converter = EnumeratedTypeConverter.class)
    })
    protected Account account;

    protected String accountUuid;

    protected Photo photo;


    public abstract Resolution gotoRegisterPage();

    /**
     * Register new account action
     *
     * @return Resoltution - back to login form
     */
    public Resolution registerNewAccount() {
        account.setPassword(EncriptionUtils.convertPasswordToMD5(account.getPassword()));
        boolean update = true;
        //if uuid==null then we create new account, else we update existing one
        if (account.getUuid() == null) {
            account.setUuid(UUID.randomUUID().toString());
            update = false;
        }

        constructPhoto(account);
        saveAccount();

        if (!update) {
            return new ForwardResolution("/public/login.jsp");
        } else {
            return new ForwardResolution("/index.jsp");
        }
    }

    public abstract void saveAccount();

    /**
     * Construts new photo entity
     *
     * @param account account to which photo belongs
     */
    private void constructPhoto(Account account) {
        if (photo != null && photo.getPictureBean() != null) {
            try {
                photo.setPicture(IOUtils.toByteArray(photo.getPictureBean().getInputStream()));
                photo.getPictureBean().delete();
                photo.setUuid(UUID.randomUUID().toString());
                account.setPhoto(Arrays.asList(photo));
            } catch (IOException e) {
                LOGGER.error(e);
            }
        }
    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

    public Photo getPhoto() {
        return photo;
    }

    public void setPhoto(Photo photo) {
        this.photo = photo;
    }

    public String getAccountUuid() {
        return accountUuid;
    }

    public void setAccountUuid(String accountUuid) {
        this.accountUuid = accountUuid;
    }

    @ValidationMethod(on = "registerNewAccount")
    public void checkPasswords(ValidationErrors validationErrors) {
        if (!account.getPassword().equals(account.getRePassword())) {
            validationErrors.add("account.rePassword", new LocalizableError("account.password.passwordsAreNotEquals"));
            validationErrors.add("account.password", new LocalizableError("account.password.passwordsAreNotEquals"));
        }
        if (accountService.getAccount(account.getUserName()) != null) {
            validationErrors.add("account.userName", new LocalizableError("account.userName.alreadyExists"));
        }
    }
}
